package com.shockweb.rpc;


import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.shockweb.common.utils.FileTools;
import com.shockweb.common.utils.PropertyFile;
import com.shockweb.client.ClientException;
import com.shockweb.client.impl.ConfigCenterClient;
import com.shockweb.rpc.config.ClientConfig;
import com.shockweb.service.ServiceServer;
import com.shockweb.service.ServiceServerException;


/**
 * 注册服务中心管理器，支持多个注册服务
 * 
 * @author 彭明华
 * 2018年2月6日 创建
 */
public class RpcManager {

	/**
	 * 多个注册服务中心的客户端管理器
	 */
	private static Map<String,ClientManager> clientManagers = new HashMap<String,ClientManager>();

	
	/**
	 * 多个注册服务中心的配置定义
	 */
	private static Map<String,ClientConfig> clientConfigs = new HashMap<String,ClientConfig>();

	/**
	 * 默认注册中心
	 */
	private static String registerCenter = null;
	
	/**
	 * 锁对象
	 */
	private static final Object LOCK = new Object();
	
	/**
	 * 设置默认注册中心
	 * @param key
	 */
	public static void setDefault(String registerCenter){
		RpcManager.registerCenter = registerCenter;
	}
	
	/**
	 * 获取默认注册中心的客户端管理器
	 * @return
	 */
	public static ClientManager getClientManager()throws RpcException{
		synchronized(LOCK){
			if(registerCenter==null || registerCenter.trim().equals("")){
				throw new RpcException("没有指定默认的注册服务中心");
			}
			return clientManagers.get(registerCenter);
		}
	}
	
	
	/**
	 * 获取某个注册中心客户端管理器
	 * @param registerCenter
	 * @return
	 */
	public static ClientManager getClientManager(String registerCenter)throws RpcException{
		synchronized(LOCK){
			if(!clientManagers.containsKey(registerCenter)){
				throw new RpcException("没有找到'" + registerCenter + "'所在的注册服务中心");
			}
			return clientManagers.get(registerCenter);
		}
	}
	
	/**
	 * 获取注册服务中心配置
	 * @param registerCenter
	 * @return
	 */
	public static ClientConfig getClientConfig(String registerCenter){
		synchronized(LOCK){
			return clientConfigs.get(registerCenter);
		}
	}
	
	/**
	 * 添加新注册服务中心
	 * @param config
	 */
	public static void addRegisterCenter(ClientConfig config)throws ClientException{
		synchronized(LOCK){
			if(clientConfigs.containsKey(config.getRegisterCenterKey())){
				throw new RpcException("'" + config.getRegisterCenterKey() + "'注册服务中心地址重复");
			}else{
				if(config.getRegisterCenterKey()==null || config.getRegisterCenterKey().trim().equals("")){
					throw new RpcException("注册服务中心config.registerCenterKey不能为空");
				}
				clientConfigs.put(config.getRegisterCenterKey(), config);
				clientManagers.put(config.getRegisterCenterKey(), new ClientManager(config));
				if(registerCenter==null){
					registerCenter = config.getRegisterCenterKey();
				}
			}
		}
	}
	
	/**
	 * 删除一个注册服务中心
	 * @param registerCenter
	 */
	public static void removeRegisterCenter(String registerCenter){
		synchronized(LOCK){
			ClientManager clientManager = clientManagers.get(registerCenter);
			clientManager.close();
			clientManagers.remove(registerCenter);
			clientConfigs.remove(registerCenter);
			if(registerCenter.equals(RpcManager.registerCenter)){
				registerCenter = null;
			}
			if(!clientConfigs.isEmpty()){
				registerCenter = clientConfigs.get(clientConfigs.keySet().iterator().next()).getRegisterCenterKey();
			}
		}
	}
	/**
	 * 通过配置文件获取默认注册中心名字
	 * @param filePath
	 * @param group
	 * @return
	 * @throws ServiceServerException
	 * @throws IOException
	 */
	public static String getRegisterCenterDefault(String filePath,String group)throws ServiceServerException,IOException{
		if(filePath.startsWith("classpath:")){
			ClassLoader classLoader = null;
			if(Thread.currentThread()!=null){
				classLoader = Thread.currentThread().getContextClassLoader();
			}else{
				classLoader = ServiceServer.class.getClassLoader();
			}
			filePath = classLoader.getResource(filePath.substring("classpath:".length())).getPath();
		}
    	String file = null;
    	if(new File(filePath).isFile()){
    		file = filePath;
    	}else if(new File(filePath).isDirectory()){
    		file = FileTools.getFullPathFileName(filePath,"config.properties");
    	}else{
    		throw new ServiceServerException("配置文件路径" + filePath + "非法");
    	}
    	Map<String,String> data = PropertyFile.read(file);
    	if(group!=null){
    		return data.get(group + ".default");
    	}else{
    		return data.get("rpc.default");
    	}
    	
	}
	/**
	 * 读取配置文件
	 * @param filePath
	 * @param rpc
	 * @return
	 * @throws ServiceServerException
	 * @throws IOException
	 */
	public static List<ClientConfig> readConfig(String filePath,String group)throws ServiceServerException,IOException{
		if(filePath.startsWith("classpath:")){
			ClassLoader classLoader = null;
			if(Thread.currentThread()!=null){
				classLoader = Thread.currentThread().getContextClassLoader();
			}else{
				classLoader = ServiceServer.class.getClassLoader();
			}
			filePath = classLoader.getResource(filePath.substring("classpath:".length())).getPath();
		}
    	String file = null;
    	if(new File(filePath).isFile()){
    		file = filePath;
    	}else if(new File(filePath).isDirectory()){
    		file = FileTools.getFullPathFileName(filePath,"config.properties");
    	}else{
    		throw new ServiceServerException("配置文件路径" + filePath + "非法");
    	}
    	Map<String,String> data = PropertyFile.read(file);
    	if(data==null){
    		throw new ServiceServerException("配置文件" + file + "内容为空");
    	}
    	if(group==null){
    		group = "rpc";
    	}
    	String rpc = group;
    	int i=1;
    	List<ClientConfig> lists = new ArrayList<ClientConfig>();
    	while(data.get(rpc + ".registerCenterKey")!=null){
    		ClientConfig config = new ClientConfig();
    		config.setRegisterCenterKey(data.get(rpc + ".registerCenterKey").replaceAll(" ", ""));
	    	if(data.get(rpc + ".registerServerUrls")!=null){
	    		config.setRegisterServerUrls(data.get(rpc + ".registerServerUrls").replaceAll(" ", ""));
	    	}
	    	if(data.containsKey(rpc + ".activeTime")){
	    		config.setActiveTime(Integer.parseInt(data.get(rpc + ".activeTime").trim()));
	    	}
	    	if(data.containsKey(rpc + ".syncThreadSleepTime")){
	    		config.setSyncThreadSleepTime(Integer.parseInt(data.get(rpc + ".syncThreadSleepTime").trim()));
	    	}
	    	if(data.containsKey(rpc + ".clientConnectTimeOut")){
	    		config.setClientConnectTimeOut(Integer.parseInt(data.get(rpc + ".clientConnectTimeOut").trim()));
	    	}
	    	if(data.containsKey(rpc + ".clientTimeOut")){
	    		config.setClientTimeOut(Integer.parseInt(data.get(rpc + ".clientTimeOut").trim()));
	    	}
	    	if(data.containsKey(rpc + ".clientSleepTime")){
	    		config.setClientSleepTime(Integer.parseInt(data.get(rpc + ".clientSleepTime").trim()));
	    	}
	    	if(data.containsKey(rpc + ".clientIdleStateTime")){
	    		config.setClientIdleStateTime(Integer.parseInt(data.get(rpc + ".clientIdleStateTime").trim()));
	    	}
	    	lists.add(config);
	    	rpc = group + i;
	    	i++;
    	}
    	return lists==null || lists.isEmpty()?null:lists;
	}
	
	/**
	 * 启动多个注册中心的微服务客户端,并指定默认的注册中心
	 * @param propFilePath
	 * @throws IOException
	 */
    public static void init(List<ClientConfig> configs,String registerCenterDefault)throws ServiceServerException{
    	try{
    		for(ClientConfig config:configs){
		    	addRegisterCenter(config);
	    	}
        	if(registerCenterDefault!=null){
        		setDefault(registerCenterDefault.replaceAll(" ", ""));
        	}
    	}catch(Exception e){
    		throw new ServiceServerException("启动微服务客户端失败",e);
    	}
    }
    
	/**
	 * 通过配置中心，启动多个注册中心的微服务客户端
	 * @param propFilePath
	 * @throws IOException
	 */
    public static void init(String configCenterUrls,String group)throws ServiceServerException{
    	ConfigCenterClient client = null;
    	try{
    		client = ConfigCenterClient.getConfigCenterClient(configCenterUrls);
    		List<ClientConfig> lists = new ArrayList<ClientConfig>();
        	if(group==null){
        		group = "rpc";
        	}
        	String rpc = group;
        	int i=1;
        	String registerCenterKey = client.getConfig(rpc, "registerCenterKey");
        	while(registerCenterKey!=null){
        		ClientConfig config = new ClientConfig();
        		config.setRegisterCenterKey(registerCenterKey.replaceAll(" ", ""));
        		String registerServerUrls = client.getConfig(rpc, "registerServerUrls");
    	    	if(registerServerUrls!=null){
    	    		config.setRegisterServerUrls(registerServerUrls.replaceAll(" ", ""));
    	    	}
    	    	String activeTime = client.getConfig(rpc, "activeTime");
    	    	if(activeTime!=null){
    	    		config.setActiveTime(Integer.parseInt(activeTime.trim()));
    	    	}
    	    	String syncThreadSleepTime = client.getConfig(rpc, "syncThreadSleepTime");
    	    	if(syncThreadSleepTime!=null){
    	    		config.setSyncThreadSleepTime(Integer.parseInt(syncThreadSleepTime.trim()));
    	    	}
    	    	String clientConnectTimeOut = client.getConfig(rpc, "clientConnectTimeOut");
    	    	if(clientConnectTimeOut!=null){
    	    		config.setClientConnectTimeOut(Integer.parseInt(clientConnectTimeOut.trim()));
    	    	}
    	    	String clientTimeOut = client.getConfig(rpc, "clientTimeOut");
    	    	if(clientTimeOut!=null){
    	    		config.setClientTimeOut(Integer.parseInt(clientTimeOut.trim()));
    	    	}
    	    	String clientSleepTime = client.getConfig(rpc, "clientSleepTime");
    	    	if(clientSleepTime!=null){
    	    		config.setClientSleepTime(Integer.parseInt(clientSleepTime.trim()));
    	    	}
    	    	String clientIdleStateTime = client.getConfig(rpc, "clientIdleStateTime");
    	    	if(clientIdleStateTime!=null){
    	    		config.setClientIdleStateTime(Integer.parseInt(clientIdleStateTime.trim()));
    	    	}
    	    	lists.add(config);
    	    	rpc = group + i;
    	    	i++;
    	    	registerCenterKey = client.getConfig(rpc, "registerCenterKey");
        	}
        	String registerCenterDefault = client.getConfig(group, "registerCenterDefault");
    		for(ClientConfig config:lists){
		    	addRegisterCenter(config);
	    	}
        	if(registerCenterDefault!=null){
        		setDefault(registerCenterDefault.replaceAll(" ", ""));
        	}
    	}catch(Exception e){
    		throw new ServiceServerException("启动微服务客户端失败",e);
    	}finally{
    		if(client!=null){
    			client.close();
    		}
    	}
    }
    
	/**
	 * 通过配置文件，启动多个注册中心的微服务客户端
	 * @param propFilePath
	 * @throws IOException
	 */
    public static void init(String filePath)throws ServiceServerException{
    	try{
    		List<ClientConfig> lists = readConfig(filePath,"rpc");
    		for(ClientConfig config:lists){
		    	addRegisterCenter(config);
	    	}
        	String registerCenterDefault = getRegisterCenterDefault(filePath,"rpc");
        	if(registerCenterDefault!=null){
        		setDefault(registerCenterDefault.replaceAll(" ", ""));
        	}
    	}catch(ServiceServerException e){
    		throw e;
    	}catch(Exception e){
    		throw new ServiceServerException("启动微服务客户端失败",e);
    	}
    }
    
	/**
	 * 所有的注册信息
	 */
	public static void close(){
		synchronized(LOCK){
			Iterator<Entry<String,ClientManager>> its = clientManagers.entrySet().iterator();
			while(its.hasNext()){
				Entry<String,ClientManager> entry = its.next();
				entry.getValue().close();
			}
			clientManagers.clear();
			clientConfigs.clear();
			registerCenter = null;
		}
	}
}
